package Sdo.terminalfx;

import com.pty4j.PtyProcess;
import Sdo.terminalfx.config.TabNameGenerator;
import Sdo.terminalfx.config.TerminalConfig;
import Sdo.terminalfx.helper.IOHelper;
import Sdo.terminalfx.helper.ThreadHelper;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.Tab;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;

import java.io.Reader;
import java.io.Writer;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Objects;

import java.util.Timer;
import java.util.TimerTask;
public class TerminalTab extends Tab {

	private final Terminal terminal;
	private final TabNameGenerator tabNameGenerator;
	private static final String NEW_TAB_KEY = "T";
	BorderPane pane;
	VBox vb = new VBox();// 提示信息展示的控件
	static ProgressBar pbar = new ProgressBar();
	
	static Label systemInfo = new Label();

	public ProgressBar getBar() {

		return pbar;
	}

	public Label getsysteminfo() {
		return systemInfo;
		
	}
	public void setInfoText(String info,Long tm) {
		Label txtInfo = new Label();
		// txtInfo.prefWidthProperty().bind(pane.widthProperty());
		txtInfo.setAlignment(Pos.CENTER);
		txtInfo.setTextFill(Color.web("#ff0000", 0.8));
//
//		txtInfo.setVisible(false);
//		txtInfo.setManaged(false);

		vb.getChildren().add(txtInfo);
		txtInfo.setManaged(true);
		txtInfo.setVisible(true);
		txtInfo.setText(info);
		Timer t = new Timer();
		t.schedule(new TimerTask() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				txtInfo.setManaged(false);
				txtInfo.setVisible(false);
				//System.out.println("自动消失");
				t.cancel();
			}
		}, tm, 1);

	}

	public TerminalTab(TerminalConfig terminalConfig, TabNameGenerator tabNameGenerator, Path terminalPath,
			BorderPane pane) {

		this(new Terminal(terminalConfig, terminalPath, pbar,systemInfo), tabNameGenerator,pane);

	}

	public TerminalTab(Terminal terminal, TabNameGenerator tabNameGenerator, BorderPane pane) {
		this.pane = pane;
		this.terminal = terminal;
		this.tabNameGenerator = tabNameGenerator;

		this.terminal.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
			public void handle(KeyEvent event) {

				if (event.isShortcutDown() && NEW_TAB_KEY.equalsIgnoreCase(event.getText())) {
					newTerminal();
				}
			}
		});

		this.setOnCloseRequest(new EventHandler<Event>() {
			public void handle(Event event) {
				event.consume();
				closeTerminal();
			}
		});

		final String tabName = getTabNameGenerator().next();
		setText(tabName);
		final ContextMenu contextMenu = new ContextMenu();

		final MenuItem closeOthers = new MenuItem("Close Others");
		final MenuItem closeAll = new MenuItem("Close All");

		closeAll.setOnAction(this::closeAllTerminal);
		closeOthers.setOnAction(this::closeOtherTerminals);

		contextMenu.getItems().addAll(closeOthers, closeAll);
		this.setContextMenu(contextMenu);

		pbar.prefWidthProperty().bind(pane.widthProperty());

		pbar.setVisible(false);
		pbar.setManaged(false);

		
		systemInfo.prefWidthProperty().bind(pane.widthProperty());
		systemInfo.setAlignment(Pos.CENTER);
		systemInfo.setTextFill(Color.web("#ff0000", 0.8));

		systemInfo.setVisible(false);
		systemInfo.setManaged(false);
		
		
		vb.getChildren().addAll(pbar,systemInfo);

		pane.setTop(vb);
		pane.setCenter(terminal);
		setContent(pane);

	}

	private void closeOtherTerminals(ActionEvent actionEvent) {
		final ObservableList<Tab> tabs = FXCollections.observableArrayList(this.getTabPane().getTabs());
		ArrayList<Tab> markedTabs = new ArrayList<Tab>();

		for (final Tab tab : tabs) {

			if (tab != getTabPane().getSelectionModel().getSelectedItem())
				markedTabs.add(tab);

		}

		getTabPane().getTabs().removeAll(markedTabs);
	}

	private void closeAllTerminal(ActionEvent actionEvent) {
		this.getTabPane().getTabs().clear();
	}

	public void newTerminal(ActionEvent... actionEvent) {

		final TerminalTab terminalTab = new TerminalTab(getTerminalConfig(), getTabNameGenerator(), getTerminalPath(),
				pane);

		getTabPane().getTabs().add(terminalTab);
		getTabPane().getSelectionModel().select(terminalTab);
	}

	public void closeTerminal(ActionEvent... actionEvent) {
		ThreadHelper.runActionLater(() -> {
			final ObservableList<Tab> tabs = this.getTabPane().getTabs();
			if (tabs.size() == 1) {
				newTerminal(actionEvent);
			}
			tabs.remove(this);

			destroy();
		});
	}

	public void destroy() {
		ThreadHelper.start(() -> {
			while (Objects.isNull(getProcess())) {
				ThreadHelper.sleep(250);
			}
			getProcess().destroy();
			IOHelper.close(getInputReader(), getErrorReader(), getOutputWriter());
		});
	}

	public void onTerminalFxReady(Runnable onReadyAction) {
		terminal.onTerminalFxReady(onReadyAction);
	}

	public TabNameGenerator getTabNameGenerator() {
		return tabNameGenerator;
	}

	public Path getTerminalPath() {
		return terminal.getTerminalPath();
	}

	public TerminalConfig getTerminalConfig() {
		return terminal.getTerminalConfig();
	}

	public PtyProcess getProcess() {
		return terminal.getProcess();
	}

	public Reader getInputReader() {
		return terminal.getInputReader();
	}

	public Reader getErrorReader() {
		return terminal.getErrorReader();
	}

	public Writer getOutputWriter() {
		return terminal.getOutputWriter();
	}

	public Terminal getTerminal() {
		return terminal;
	}
}